using System;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.UI;

namespace Galplay {
  public class GameManager : MonoBehaviour {
#if UNITY_ANDROID && !UNITY_EDITOR
        static public bool IsAndroid {get; private set;} = true;
#else
    static public bool IsAndroid { get; private set; } = false;
#endif

    public static GameManager Instance { get; private set; }
    public static GameScenePlayer ScenePlayer { get => GameScenePlayer.Instance; }

    public TMP_Text statusText;

    public Slider process_slider;
    public AudioSource bgmSource;
    public AudioSource voiceSource;
    public AudioSource bgsSource;
    public AudioSource seSource;
    public bool usePitchChange = false;
    public GameObject scrollView;
    public GameObject scrollContent;
    public GameObject chapterButton;
    [Tooltip("用于管理菜单")]
    public MenuManager menuManager;
    [Tooltip("BGM的Master音量"), Range(0, 1)]
    public float bgm_volume = 1.0f;

    public Image backgroundImage;

    // 全局的播放速度
    public float PlaySpeed { get; set; } = 1.0f;
    // 是否使用Value改变Process
    public bool UseValueChanged { get; set; }

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Awake() {
      // 设置全局信息
      Instance = this;
      // 游戏管理器是常驻存在的。
      DontDestroyOnLoad(gameObject);
    }

    void Start() {
      try {
        StartCurrentGame();
      } catch (System.Exception ex) {
        Debuger.LogError($"Failed to SetBg: {ex.Message}");
      }
    }

    internal void SetGame(GameProject game) {
      ProjectManager.Instance.SetGame(game);
      LoadCurrentGameChapter();
    }

    public void LoadCurrentGameChapter() {
      Game.Load(() => {
        // 切到到Chapter
        menuManager.CloseMenu();
        menuManager.ToggleChapters();
      });
    }

    public void StartCurrentGame() {
      Game.Load(() => {
        // 开始播放第一个Scene
        PlayScene(Game.Scenes[0]);
      });
    }

    public void PlayScene(GameScene gameScene) {
      UseValueChanged = false;
      process_slider.value = 0.0f;
      menuManager.CloseMenu();
      CurrentScene = gameScene;
      GameScenePlayer.Instance.Play(gameScene);
    }



    public GameProject Game { get => ProjectManager.Instance.Current; }
    public GameScene CurrentScene { get; private set; }

    // Update is called once per frame
    void Update() {

    }

    void SetStatus(string text) {
      statusText.text = text;
    }

    public void PlayBgm(AudioClip clip, float volume = 1.0f) {
      bgmSource.clip = clip;
      bgmSource.loop = true;
      bgmSource.volume = volume * bgm_volume;
      bgmSource.Play();
    }

    public void PlayBgm(string relativePath, float volume = 1.0f) {
      LoadSound(relativePath, clip => { PlayBgm(clip, volume); });
    }

    internal void PlayBgm(int bgmID) {
      var item = SoundManager.Instance.GetSound("BGM", bgmID);
      if (item == null) {
        Debug.LogError($"BGM {bgmID} not found!");
      } else {
        PlayBgm(item.Path, item.Volume);
      }
    }

    public void PlaySe(AudioClip clip, float volume = 1.0f) {
      seSource.PlayOneShot(clip, volume);
    }

    public void PlaySe(string relativePath, float volume = 1.0f) {
      LoadSound(relativePath, clip => { PlaySe(clip, volume); });
    }

    public void PlayVoice(int voice) {
      var item = SoundManager.Instance.GetSound("SE", voice);
      if (item == null) {
        Debug.LogError($"Voice(SE) {voice} not found!");
      } else {
        PlayVoice(item.Path, item.Volume);
        ScenePlayer.SetAutoTime(item.Time / PlaySpeed);
      }
    }

    public void PlayVoice(AudioClip clip, float volume = 1.0f) {
      if (PlaySpeed == 1.0f || usePitchChange == false) {

        voiceSource.loop = false;
        voiceSource.volume = volume;
        voiceSource.clip = clip;
        voiceSource.Play();
      } else {
        // 停止当前播放
        voiceSource.Stop();

        // 设置clip和速度
        voiceSource.clip = clip;
        voiceSource.pitch = 1.0f; // 保持原始音高

        // 使用DSP时间缩放控制速度
        double startTime = AudioSettings.dspTime + 0.1;
        voiceSource.PlayScheduled(startTime);

        // 计算调整后的播放时长
        double adjustedDuration = clip.length / PlaySpeed;
        voiceSource.SetScheduledEndTime(startTime + adjustedDuration);
      }
    }

    public void PlayVoice(string relativePath, float volume = 1.0f) {
      LoadSound(relativePath, clip => { PlayVoice(clip, volume); });
    }

    public void PlayBgs(AudioClip clip, float volume = 1.0f) {
      bgsSource.clip = clip;
      bgsSource.loop = true;
      bgsSource.volume = volume;
      bgsSource.Play();
    }

    public void PlayBgs(string relativePath, float volume = 1.0f) {
      LoadSound(relativePath, clip => { PlayBgs(clip, volume); });
    }

    public void StopBgs() {
      bgsSource.Stop();
    }
    public void StopBgm() {
      bgmSource.Stop();
    }
    public void StopSe() {
      seSource.Stop();
    }
    public void StopVoice() {
      voiceSource.Stop();
    }

    internal void PlayBgs(int bgsID) {
      var item = SoundManager.Instance.GetSound("BGS", bgsID);
      if (item == null) {
        Debug.LogError($"BGS {bgsID} not found!");
      } else {
        PlayBgs(item.Path, item.Volume);
      }
    }

    public void LoadSound(string relativePath, Action<AudioClip> action) {
      try {
        var file = Game.GetAssetFile(relativePath);
        if (file == null) { return;}
        GameResources.Instance.LoadAudioAsync(file, (audioClip) => {
          if (audioClip != null) {
            action.Invoke(audioClip);
          }
        });
      } catch (Exception ex) {
        Debuger.LogError($"Failed to Load sound: {relativePath}: {ex.Message}");
      }
    }


    public void SetBg(string relativePath) {
      var file = Game.GetAssetFile(relativePath);
      GameResources.Instance.LoadImageAsync(file, (sprite) => {
        if (sprite != null) {
          // 加载成功，使用sprite
          backgroundImage.sprite = sprite;
        } else {
          Debuger.LogError($"{relativePath} load failed!");
        }
      });
    }

    public static string GetAssets(string relativePath) {
      return ProjectManager.Instance.Current.GetAsset(relativePath);
    }

    public static void SetImage(Image img, string fullPath) {
      GameResources.Instance.LoadImageAsync(fullPath, (sprite) => {
        if (sprite != null) {
          // 加载成功，使用sprite
          img.sprite = sprite;
        } else {
          Debuger.LogError($"{fullPath} load failed!");
        }
      });
    }

    public void SetImageAsset(Image img, string relativePath) {
      var file = Game.GetAssetFile(relativePath);
      if (file == null) { return; }
      GameResources.Instance.LoadImageAsync(file, (sprite) => {
        if (sprite != null) {
          // 加载成功，使用sprite
          img.sprite = sprite;
        } else {
          Debuger.LogError($"{file.Path} load failed!");
        }
      });
    }


    private float _lastUpdateTime;
    private float _updateInterval = 0.1f; // 限制更新频率
    public void OnSliderValueChangedOptimized(float value) {
      if (!UseValueChanged) {
        return;
      }

      if (Time.time - _lastUpdateTime < _updateInterval)
        return;

      _lastUpdateTime = Time.time;
      ScenePlayer.SetProcess(value);
    }


    public float ScaleRate {
      get {
        return UiUtils.GetResolutionScale(Game.Width, Game.Height);
      }
    }

    internal void SetProcessOnly(float v) {
      UseValueChanged = false;
      process_slider.value = Mathf.Clamp(v, 0.0f, 1.0f);
      UseValueChanged = true;
    }

  }
}